// @Date         2021-11-16
// @Author       Aaron Zhang
// @Description
// @FileName      provider.go

package log

import (
	"path/filepath"
	"zin/config"
	"zin/framework"
	"zin/framework/contract"
	"zin/framework/provider/log/formatter"
	"zin/framework/util"
)

type ProviderLog struct {
	CtxFielder contract.CtxFielder
}

func (p *ProviderLog) Register(c framework.Container) framework.NewInstance {
	cfg := config.Conf.Log
	//根据配置文件，选择日志存储驱动

	switch cfg.Driver {
	case "console":
		return NewProviderServiceLogConsole
	case "file":
		return NewProviderServiceLogFile
	case "both":
		return NewProviderServiceLogBoth
	default:
		return NewProviderServiceLogConsole
	}
}

func (p *ProviderLog) Boot(c framework.Container) error {
	return nil
}

func (p *ProviderLog) IsDefer() bool {
	return false
}

func (p *ProviderLog) Params(param map[string]interface{}) map[string]interface{} {
	cfg := config.Conf.Log

	folder := "logs"
	file := "zin.log"
	appLogFolder := util.GetAppProvider().LogFolder()

	if appLogFolder != "" {
		folder = appLogFolder
	}
	if cfg.File != "" {
		file = cfg.File
	}

	//日志级别
	param["level"] = getLogLevel(cfg.Level)

	if param["level"].(contract.LogLevel) == contract.LogLevelUnknown {
		level := contract.LogLevelDebug
		param["level"] = level
	}

	//日志文件
	param["file"] = file

	//ctx内容
	param["ctxFielder"] = p.CtxFielder

	//日志目录
	param["folder"] = folder

	//格式化
	param["formatter"] = getFormatter(cfg.Formatter)

	//日志文件的绝对路径
	param["log_file"] = filepath.Join(folder, file)

	//是否开启切割
	param["enable_rotate"] = cfg.EnableRotate

	return param
}

func (p *ProviderLog) Name() string {
	return contract.ProviderKeyLog
}

func getLogLevel(level string) contract.LogLevel {
	switch level {
	case "panic":
		return contract.LogLevelPanic
	case "falter":
		return contract.LogLevelFalter
	case "error":
		return contract.LogLevelError
	case "info":
		return contract.LogLevelInfo
	case "warn":
		return contract.LogLevelWarn
	case "debug":
		return contract.LogLevelDebug
	case "trace":
		return contract.LogLevelTrace
	}

	return contract.LogLevelUnknown
}

//get formatter [ json or text ]
func getFormatter(format string) contract.Formatter {
	switch format {
	case "json":
		return formatter.JsonFormatter
	case "text":
		return formatter.TextFormatter
	default:
		return formatter.JsonFormatter
	}
}
